#ifndef __COLA_H_INCLUDED__
#define __COLA_H_INCLUDED__

#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <errno.h>

#include "../GenericException.h"

template <class T> class Cola{
private:
	key_t clave;
	int id;
	bool conectado;
	
public:
	Cola();

	/** 
	 * Se conecta a la cola correspondiente al nombre de archivo y
	 * letra dadas.
	 * 
	 * @param archivo Nombre del archivo de la cola.
	 * @param letra Id de la cola.
	 * 
	 * @return Devuelve 0 si no se pudo conectar a la
	 * cola. Devuelve 1 si la cola no existía y se creó
	 * satisfactoriamente. Devuelve 2 si se pudo conactar y la
	 * cola ya existía.
	 */
	int conectar(char* archivo, char letra);

	void desconectar();

	~Cola();
	int escribir(T dato);
	void leer(T* buffer, long tipo);
	bool estaConectada(){ return conectado;}
};

template <class T> Cola<T>::Cola(){
	conectado=false;
}

template <class T> int Cola<T>::conectar(char* archivo,char letra){

	if(conectado)
		desconectar();

	int retorno = 0;
	clave = ftok (archivo, letra);
	
	if (clave == -1 )
		throw  GenericException("El proceso no pudo conectarse a la cola de mensajes. Error en ftok.");

	id = msgget (this->clave,0666|IPC_CREAT|IPC_EXCL);
	
	if (id == -1){
		if(errno == EEXIST){
			retorno = 2;
			id = msgget (this->clave,0666);
		}
		if(id==-1){
			retorno = 0;
			throw  GenericException("El proceso no pudo conectarse a la cola de mensajes. Error en msgget.");
			return retorno;
		}
	}
	else
		retorno = 1;

	conectado=true;

	return retorno;
}

template <class T> void Cola<T>::desconectar(){
	if(conectado){
		msgctl(this->id,IPC_RMID,NULL);
		conectado = false;
	}
}

template <class T> Cola<T>::~Cola(){
	desconectar();
}

template <class T> int Cola<T>::escribir(T dato){
	int resultado = -1;
	if(conectado)
		resultado = msgsnd(this->id,(const void *)&dato,sizeof(T),0);
	return resultado;
}

template <class T> void Cola<T>::leer(T* buffer, long tipo){
	if(msgrcv(this->id,(void *)buffer,sizeof(T),tipo,0) == -1)
		throw GenericException("No se pudo leer un mensaje de la cola.");
}

#endif //__COLA_H_INCLUDED__
